package demo3

import (
	"fmt"
)

// TestDemo34 Go语言中的循环语句只支持 for 关键字，而不支持 while 和 do-while 结构
func TestDemo34() {
	// 基本的循环
	sum1 := 0
	for i := 0; i < 10; i++ {
		sum1 += i
	}
	fmt.Println("sum1求和: ", sum1)

	// 无限循环的场景，实现其他语言中的 for(;;){} 和 do{} while(1);
	sum2 := 0
	for {
		sum2++
		if sum2 > 100 {
			fmt.Println("sum1: ", sum2)
			// 同其他语言一样， break 终端循环
			break
		}
	}

	/*
		go 循环注意点：
			1. 左花括号{必须与 for 处于同一行。
			2. Go语言中的 for 循环与 C语言一样，都允许在循环条件中定义和初始化变量，
					唯一的区别是，Go语言不支持以逗号为间隔的多个赋值语句，必须使用平行赋值的方式来初始化多个变量。
			3. Go语言的 for 循环同样支持 continue 和 break 来控制循环，
					但是它提供了一个更高级的 break，可以选择中断哪一个循环，如下例：
	*/
OuterLoop:
	for i := 2; i < 6; i++ {
		fmt.Println(i)
		for j := 0; j < 5; j++ {
			fmt.Println(j)
			if i == 4 {
				fmt.Printf("i j is %d, %d\n", i, j)
				break OuterLoop
			}
		}
	}

	/*
		for 中的初始语句——开始循环时执行的语句
			1. 初始语句是在第一次循环前执行的语句，一般使用初始语句执行变量初始化，
			2. 如果变量在此处被声明，其作用域将被局限在这个 for 的范畴内。
					初始语句可以被忽略，但是初始语句之后的分号必须要写，代码如下：
			3. 这段代码将 step 放在 for 的前面进行初始化，for 中没有初始语句，此时 step 的作用域就比在初始语句中声明 step 要大。
	*/
	step := 2
	for ; step > 0; step-- {
		fmt.Println(step)
	}

	// break 跳出循环
	fmt.Println("break")
	for i := 0; i < 10; i++ {
		fmt.Println(i)
		if i > 5 {
			break
		}
	}
	fmt.Println("continue")
	// continue 中断当前的循环，继续下次的循环
	for i := 0; i < 10; i++ {
		if i == 7 {
			continue
		}
		fmt.Println(i)
	}

	/*
		无限循环
		1. 结束循环时带可执行语句的无限循环
		2. 无限循环
		3. 只有一个循环条件的循环
	*/

	// 下面代码忽略条件表达式，但是保留结束语句，代码如下：
	var i int
	for ; ; i++ {
		if i > 10 {
			break
		}
	}

	// 上面的代码还可以改写为更美观的写法，代码如下：
	var j int
	for {
		if j > 10 {
			break
		}
		j++
	}

	// 只有一个循环条件的循环
	// 在上面代码的基础上进一步简化代码，将 if 判断整合到 for 中，变为下面的代码：
	// 上面这段代码其实类似于其他编程语言中的 while，在 while 后添加一个条件表达式，满足条件表达式时持续循环，否则结束循环。
	var k int
	for k <= 10 {
		k++
	}
	fmt.Println(k)

	// return 退出循环
	for i := 0; i < 10; i++ {
		fmt.Println(i)
		if i == 5 {
			break
			// return 会导致退出当前的函数
			// return
		}
	}

	/* 输出 9 * 9 乘法表 */
	// 遍历, 决定处理第几行
	for j := 1; j <= 9; j++ {
		// 遍历, 决定处理第几行
		for k := 1; k <= j; k++ {
			fmt.Printf("%d*%d=%d ", j, k, j*k)
		}

		// 手动生成回车
		fmt.Println()
	}
}
